// 版权所有2011 Go作者。版权所有。
// 此源代码的使用受BSD样式的约束
// 可以在许可证文件中找到的许可证。

package driver

import (
	"fmt"
	"reflect"
	"strconv"
	"time"
)

// ValueConverter是提供ConvertValue方法的接口。
// None
// ValueConverter的各种实现由
// 驱动程序包，提供一致的转换实现
// 司机之间。ValueConverter有多种用途：
// None
// *从sql包提供的值类型转换
// 输入数据库表的特定列类型，并确保
// 适合，例如确保特定的int64适合
// 表的uint16列。
// None
// *将数据库中给定的值转换为
// 驱动程序值类型。
// None
// *通过sql包，用于从驱动程序的值类型转换
// 到用户在扫描中的类型。
type ValueConverter interface {
	// ConvertValue将值转换为驱动程序值。
	ConvertValue(v interface{}) (Value, error)
}

// Valuer是提供值方法的接口。
// None
// 实现Valuer接口的类型能够转换
// 它们本身就是驱动因素的价值。
type Valuer interface {
	// 值返回驱动程序值。
	// 价值观不能恐慌。
	Value() (Value, error)
}

// Bool是一个将输入值转换为Bool的值转换器。
// None
// 转换规则如下：
// -布尔值返回不变
// -对于整数类型，
// 1是真的
// 0是假的，
// 其他整数是错误的
// -对于字符串和[]字节，规则与strconv.ParseBool相同
// -所有其他类型都是错误
var Bool boolType

type boolType struct{}

var _ ValueConverter = boolType{}

func (boolType) String() string { return "Bool" }

func (boolType) ConvertValue(src interface{}) (Value, error) {
	switch s := src.(type) {
	case bool:
		return s, nil
	case string:
		b, err := strconv.ParseBool(s)
		if err != nil {
			return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
		}
		return b, nil
	case []byte:
		b, err := strconv.ParseBool(string(s))
		if err != nil {
			return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
		}
		return b, nil
	}

	sv := reflect.ValueOf(src)
	switch sv.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		iv := sv.Int()
		if iv == 1 || iv == 0 {
			return iv == 1, nil
		}
		return nil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", iv)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		uv := sv.Uint()
		if uv == 1 || uv == 0 {
			return uv == 1, nil
		}
		return nil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", uv)
	}

	return nil, fmt.Errorf("sql/driver: couldn't convert %v (%T) into type bool", src, src)
}

// Int32是一个将输入值转换为int64的值转换器，
// 遵守int32值的限制。
var Int32 int32Type

type int32Type struct{}

var _ ValueConverter = int32Type{}

func (int32Type) ConvertValue(v interface{}) (Value, error) {
	rv := reflect.ValueOf(v)
	switch rv.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		i64 := rv.Int()
		if i64 > (1<<31)-1 || i64 < -(1<<31) {
			return nil, fmt.Errorf("sql/driver: value %d overflows int32", v)
		}
		return i64, nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		u64 := rv.Uint()
		if u64 > (1<<31)-1 {
			return nil, fmt.Errorf("sql/driver: value %d overflows int32", v)
		}
		return int64(u64), nil
	case reflect.String:
		i, err := strconv.Atoi(rv.String())
		if err != nil {
			return nil, fmt.Errorf("sql/driver: value %q can't be converted to int32", v)
		}
		return int64(i), nil
	}
	return nil, fmt.Errorf("sql/driver: unsupported value %v (type %T) converting to int32", v, v)
}

// String是一个将其输入转换为字符串的ValueConverter。
// 如果该值已经是字符串或[]字节，则该值不变。
// 如果该值是另一种类型，则将转换为字符串
// 使用fmt.Sprintf（“%v”，v）。
var String stringType

type stringType struct{}

func (stringType) ConvertValue(v interface{}) (Value, error) {
	switch v.(type) {
	case string, []byte:
		return v, nil
	}
	return fmt.Sprintf("%v", v), nil
}

// Null是通过允许nil实现ValueConverter的类型
// 值，但以其他方式委托给另一个ValueConverter。
type Null struct {
	Converter ValueConverter
}

func (n Null) ConvertValue(v interface{}) (Value, error) {
	if v == nil {
		return nil, nil
	}
	return n.Converter.ConvertValue(v)
}

// NotNull是通过禁止nil实现ValueConverter的类型
// 值，但以其他方式委托给另一个ValueConverter。
type NotNull struct {
	Converter ValueConverter
}

func (n NotNull) ConvertValue(v interface{}) (Value, error) {
	if v == nil {
		return nil, fmt.Errorf("nil value not allowed")
	}
	return n.Converter.ConvertValue(v)
}

// IsValue报告v是否为有效的值参数类型。
func IsValue(v interface{}) bool {
	if v == nil {
		return true
	}
	switch v.(type) {
	case []byte, bool, float64, int64, string, time.Time:
		return true
	case decimalDecompose:
		return true
	}
	return false
}

// IsScanValue等同于IsValue。
// 它的存在是为了兼容性。
func IsScanValue(v interface{}) bool {
	return IsValue(v)
}

// DefaultParameterConverter是的默认实现
// Stmt未实现时使用的ValueConverter
// 列转换器。
// None
// DefaultParameterConverter在以下情况下直接返回其参数
// IsValue（arg）。否则，如果参数实现Valuer，则其
// Value方法用于返回一个值。作为备用方案，提供了
// 参数的基础类型用于将其转换为值：
// 基础整数类型转换为int64，浮点数转换为浮点数64，
// bool、string和[]字节本身。如果参数为零
// 指针，ConvertValue返回一个nil值。如果论点是
// 非nil指针，它被取消引用并调用ConvertValue
// 递归地。其他类型是错误的。
var DefaultParameterConverter defaultConverter

type defaultConverter struct{}

var _ ValueConverter = defaultConverter{}

var valuerReflectType = reflect.TypeOf((*Valuer)(nil)).Elem()

// callValuerValue返回vr.Value（），但有一个例外：
// 如果vr.Value是指针类型上自动生成的方法，则
// 指针为nil，它将在运行时在panicwrap中死机
// 方法将其视为零。
// 第8415期。
// None
// 这样人们就可以在值类型和
// 仍然使用指向这些类型的nil指针来表示nil/NULL，就像
// string/*string。
// None
// 此函数镜像在数据库/sql包中。
func callValuerValue(vr Valuer) (v Value, err error) {
	if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Ptr &&
		rv.IsNil() &&
		rv.Type().Elem().Implements(valuerReflectType) {
		return nil, nil
	}
	return vr.Value()
}

func (defaultConverter) ConvertValue(v interface{}) (Value, error) {
	if IsValue(v) {
		return v, nil
	}

	switch vr := v.(type) {
	case Valuer:
		sv, err := callValuerValue(vr)
		if err != nil {
			return nil, err
		}
		if !IsValue(sv) {
			return nil, fmt.Errorf("non-Value type %T returned from Value", sv)
		}
		return sv, nil

	// 现在，继续选择Valuer接口而不是decimal decompose接口。
	case decimalDecompose:
		return vr, nil
	}

	rv := reflect.ValueOf(v)
	switch rv.Kind() {
	case reflect.Ptr:
		// 间接指针
		if rv.IsNil() {
			return nil, nil
		} else {
			return defaultConverter{}.ConvertValue(rv.Elem().Interface())
		}
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return rv.Int(), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
		return int64(rv.Uint()), nil
	case reflect.Uint64:
		u64 := rv.Uint()
		if u64 >= 1<<63 {
			return nil, fmt.Errorf("uint64 values with high bit set are not supported")
		}
		return int64(u64), nil
	case reflect.Float32, reflect.Float64:
		return rv.Float(), nil
	case reflect.Bool:
		return rv.Bool(), nil
	case reflect.Slice:
		ek := rv.Type().Elem().Kind()
		if ek == reflect.Uint8 {
			return rv.Bytes(), nil
		}
		return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, ek)
	case reflect.String:
		return rv.String(), nil
	}
	return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
}

type decimalDecompose interface {
	// 分解将内部十进制状态返回为多个部分。
	// 如果提供的buf具有足够的容量，则buf可作为系数返回，并带有
	// 值集和长度集（视情况而定）。
	Decompose(buf []byte) (form byte, negative bool, coefficient []byte, exponent int32)
}
